import { Application } from "mydog";
import { Op, Sequelize } from "sequelize";
import Doudizhu from "../models/doudizhu";
import User from "../models/user";

class DBManager {

  private static _instance: DBManager | undefined = undefined;
  public static getInstance(): DBManager {
    if (!this._instance) {
      this._instance = new DBManager();
    }
    return this._instance;
  }

  private constructor() { }

  private _app: Application = null as any;
  private _connection: Sequelize = null as any;

  public init(app: Application, connection: Sequelize) {
    this._app = app;
    this._connection = connection;
  }

  public async registerUser(username: string, password: string): Promise<User | null> {
    try {
      let user = await User.findOne({ where: { username: username }, paranoid: false }); // 查询包含软删除的记录
      if (!!user) {
        if (!!user.deletedAt) {
          await user.restore();
          // await user.update({ username, password, nickname: username }); // 会触发2次 afterValidate
          await User.update({ username, password, nickname: username }, { where: { id: user.id } });
        } else {
          return null;
        }
      } else {
        user = await User.create({ username, password, nickname: username })
      }
      return user;
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  public async getUserById(id: number) {
    try {
      return await User.findByPk(id);
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  public async getUserByUsername(username: string) {
    try {
      return await User.findOne({ where: { username: username } });
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  public async rename(uid: number, newname: string) {
    try {
      const result = await User.update({ nickname: newname }, { where: { id: uid } });
      return (!!result && result.length > 0)
    } catch (error) {
      console.error(error);
      return false;
    }
  }

  public async getDoudizhuInfo(uid: number) {
    try {
      return await Doudizhu.findByPk(uid);
    } catch (error) {
      console.error(error);
      return null;
    }
  }

  public async getUsersJoinDoudizhu(uids: Array<number>) {
    try {
      const queryOption = {
        attributes: ['id', 'nickname'],
        where: { id: { [Op.or]: uids } },
        include: [{ model: Doudizhu }]
      }
      return await User.findAll(queryOption);
    } catch (error) {
      console.error(error);
      return null;
    }
  }

}

export default DBManager.getInstance();
